/**
 * 全局编辑表单容器配置
 * @author luguoxiang
 * @date 2022/9/18
 * 开源项目：https://gitee.com/lgx1992/lg-soar 求star！请给我star！请帮我点个star！
 */
import { defineAsyncComponent, provide, reactive, ref } from 'vue';
import { UseEditContainerOptions } from './types';
// import EditModal from './Modal.vue';
// import EditDrawer from './Drawer.vue';
// import EditPage from './Page.vue';
// import message from '@/config/message';
// export { EditModal, EditDrawer, EditPage };

export const EditModal = defineAsyncComponent(() => import('./Modal.vue'));
export const EditDrawer = defineAsyncComponent(() => import('./Drawer.vue'));
export const EditPage = defineAsyncComponent(() => import('./Page.vue'));

// 在这里切换全局的编辑表单容器
export const EditContainer = EditDrawer;

/**
 * 提供基本的编辑容器配置
 * @param config
 */
export function useEditContainer<T>(config: UseEditContainerOptions<T>) {
  const {
    containerRef,
    containerProps,
    formRef,
    formProps,
    getData,
    onOk,
    onClose,
    header = '',
    isUpdate = (params) => params?.id,
  } = config;
  // 表单数据
  const loading = ref<boolean>(false);
  // 表单数据
  const data = ref<T>({} as T);
  // 旧数据用于差异比对
  let oldModelJson = '';
  // 打开弹窗是传的参数
  const paramsData = ref<any>();
  // 弹窗是否打开的
  const opened = ref<boolean>(false);
  // form表单配置数据
  const formConfig = reactive({
    data: {},
    isUpdate: false,
    ...formProps,
  });

  function onOpen(params: any) {
    paramsData.value = params;
    if (isUpdate(params)) {
      // 修改数据
      containerConfig.header = `修改${header}`;
      formConfig.isUpdate = true;
      // 调用接口查询完整数据
      getData(params)
        .then((res: any) => {
          updateData(res);
        })
        .finally(() => {
          loading.value = false;
        });
      loading.value = true;
    } else {
      // 新增数据
      containerConfig.header = `新增${header}`;
      formConfig.isUpdate = false;
      // 使用传入的数据
      updateData({ ...(params ?? config.data ?? formProps?.data ?? {}) });
    }
    opened.value = true;
  }

  // 编辑容器配置数据
  const containerConfig = reactive({
    header: '',
    destroyOnClose: false,
    closeOnOverlayClick: false,
    ...containerProps,
    onOpen(params: any) {
      formRef.value?.clearValidate();
      onOpen(params);
      containerProps?.onOpen?.(params);
      config?.onOpen?.(params);
    },
    /**
     * 当点击确定按钮时
     */
    async onConfirm() {
      loading.value = true;
      try {
        await formRef.value?.validate();
        await uploadAll();
        await onOk({
          values: formRef.value?.getData(),
          data: data.value as T,
          params: paramsData.value,
          isUpdate: !!formConfig.isUpdate,
          changed: oldModelJson !== JSON.stringify(data.value),
        });
        containerRef.value.close();
        formRef.value.reset();
      } finally {
        loading.value = false;
      }
    },
    /*    /!**
     * 弹窗关闭前处理
     * @param done
     *!/
    beforeClose: (done: Function) => {
      message
        .confirm({
          enabled: oldModelJson !== JSON.stringify(data.value),
          message: closeMsg ?? '内容未保存，确定关闭吗？',
        })
        .then(() => done());
    }, */
    /**
     * 弹窗关闭后处理
     */
    onClose() {
      opened.value = false;
      formRef.value?.reset();
      onClose?.();
    },
  });

  /**
   * 更新表单数据
   * @param d
   */
  function updateData(d: any) {
    d ??= {};
    formConfig.data = d;
    data.value = d;
    oldModelJson = JSON.stringify(d);
  }

  const set: Set<any> = new Set();
  provide('register', (i: any) => {
    set.add(i);
  });
  provide('deregister', (i: any) => {
    set.delete(i);
  });

  function uploadAll() {
    const promises = [];
    for (const x of set) {
      promises.push(x());
    }
    return Promise.all(promises);
  }

  return {
    open(params?: any) {
      containerRef.value.open(params);
    },
    close() {
      containerRef.value.close();
    },
    updateData,
    uploadAll,
    containerConfig,
    formConfig,
    opened,
    params: paramsData,
    data,
    loading,
  };
}

export default EditContainer;
